﻿/*
   Copyright 2011 Softisis

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System;
using System.Collections.Generic;

namespace FOM.Interfaces
{
    /// <summary>
    /// Contract for FluentMapper manager
    /// </summary>
    /// <remarks>Copyright Softisis 2011 (France)</remarks>
    public interface IManager
    {
        /// <summary>
        /// Register a new mapping by it's name, from a type TSrc to type TDst
        /// </summary>
        /// <typeparam name="TSrc">Type of source</typeparam>
        /// <typeparam name="TDst">Type of destination</typeparam>
        /// <param name="name">Mapping name, unci, to be recalled</param>
        /// <returns>The top mapping node</returns>
        IMappingNode<TSrc, TDst> RegisterMapping<TSrc, TDst>(String name);


        /// <summary>
        /// Register a new anonymous mapping. Name is unically generated like Anonymous_[xxx], where [xxx] is an int.
        /// </summary>
        /// <typeparam name="TSrc">Type of source</typeparam>
        /// <typeparam name="TDst">Type of destination</typeparam>
        /// <returns>The top mapping node</returns>
        IMappingNode<TSrc, TDst> RegisterMapping<TSrc, TDst>();


        /// <summary>
        /// Register a new mapping by it's name, for a type (source and desta have the same type).
        /// </summary>
        /// <typeparam name="T">Source and destination type</typeparam>
        /// <param name="name">Mapping name, unci, to be recalled</param>
        /// <returns>A link to the mapping</returns>
        IMappingNode<T, T> RegisterMapping<T>(String name);

        /// <summary>
        /// Register a new mapping by it's name, for a type (source and desta have the same type).
        /// </summary>
        /// <typeparam name="TSrc">Source and destination type</typeparam>
        /// <typeparam name="TDst">Destination type</typeparam>
        /// <param name="mapping">the mapping to register</param>
        /// <param name="name">Mapping name, unique, to be recalled</param>
        /// <returns>A link to the mapping</returns>
        void RegisterMapping<TSrc, TDst>(IMappingNode<TSrc, TDst> mapping, String name);

        /// <summary>
        /// Register a new anonymous mapping on two same type.
        /// Name is unically generated like Anonymous_[xxx], where [xxx] is an int.
        /// </summary>
        /// <typeparam name="T">Source and destination type</typeparam>
        /// <returns>A link to the mapping</returns>
        IMappingNode<T, T> RegisterMapping<T>();


        /// <summary>
        /// Unregister a mapping by its name. If it does not exists, return false,
        /// otherwise true is deletion is ok.
        /// </summary>
        /// <param name="name">Mapping name</param>
        bool UnRegisterMapping(String name);


        /// <summary>
        /// Retrieve a mapping by its name
        /// </summary>
        /// <typeparam name="TSrc">Source type</typeparam>
        /// <typeparam name="TDest">Destination type</typeparam>
        /// <param name="mapname">Mapping name</param>
        /// <returns>A mapping implementation if found, null otherwise.</returns>
        IMappingNode<TSrc, TDest> GetMapping<TSrc, TDest>(String mapname);


        /// <summary>
        /// Apply the nammed mapping.
        /// </summary>
        /// <param name="name">name of the mapping. If not exist, Exception is raised.</param>
        /// <param name="src">the source object.</param>
        /// <param name="target">The target object</param>
        object ApplyMapping(String name, object src, object target);


        /// <summary>
        /// Apply the mapping pointed by rootNode
        /// </summary>
        /// <param name="rootNode">The root node of the mapping</param>
        /// <param name="src">the source object.</param>
        /// <param name="target">The target object</param>
        /// <param name="objcache">Provide the cache object used with NewInstance(true).
        /// If null, a default one is create, local to the apply mapping call.</param>
        object ApplyMapping(INode rootNode, object src, object target, IDictionary<object, object> objcache);

        /// <summary>
        /// Apply the nammed mapping. because the target is not givent, it's instanciated, according to
        /// root node parameters (newInstance, overriding type, etc ...)
        /// </summary>
        /// <param name="name">name of the mapping. If not exist, Exception is raised.</param>
        /// <param name="src">the source object.</param>
        object ApplyMapping(String name, object src);


        /// <summary>
        /// Apply the mapping staring from this node. because the target is not given, it's instanciated, according to
        /// root node parameters (newInstance, overriding type, etc ...)
        /// </summary>
        /// <param name="rootNode">Root node for mapping</param>
        /// <param name="src">the source object.</param>
        /// <param name="objcache">Provide the cache object used with NewInstance(true).
        /// If null, a default one is create, local to the apply mapping call.</param>
        object ApplyMapping(INode rootNode, object src, IDictionary<object, object> objcache);

    }
}
